﻿using System.Diagnostics;

namespace BlogsAPI.Shorteners
{
    using System;
    using System.IO;
    using System.Net;
    using Abstract;
    using System.Text.RegularExpressions;

    /// <summary>
    /// Сервис b23.ru является публичным, и предназначен для сокращения ссылок (URL), 
    /// чтобы подготовить их к последующей передаче в почте, смс, других коммуникативных сервисах,
    /// а также публикации на форумах, в блогах и веб-сайтах.
    /// </summary>
    /// <seealso cref="http://b23.ru/about/api/"/>
    /// <remarks>
    /// Получение информации обо всех ссылках возможно без всякой авторизации. 
    /// Но для добавления новых ссылок, вашему приложению понадобится при обращении указать ключ, 
    /// по которому мы узнаем, что это именно вы, и именно в ваш архив ссылок нужно добавить новую 
    /// короткую ссылку. Ключ уникален и генерируется индивидуально для каждого пользователя.
    /// Так как API мы запускаем в качестве эксперимента, то пока ограничения стоят на уровне 30 запросов 
    /// за 60 минут (начиная с момента первого запроса) для каждого ключа. Число анонимных запросов пока 
    /// не ограничено ничем.
    /// 
    /// There are only 3 functions:
    /// http://b23.ru/api/info/ehfl#
    /// http://b23.ru/api/expand/ehfl#
    /// http://b23.ru/api/shorten/http://s-c.me#
    /// </remarks>
    [SingleShortener(Link = "http://b23.ru/")]
    public class B23 : Shortener
    {
        /// <summary>
        /// Конструктор по умолчанию
        /// </summary>
        public B23()
        {
            _username = "topbot";
            _apikey = "yWztbmAf";
        }

        /// <summary>
        /// Заполняем данными пользователя
        /// </summary>
        /// <param name="username">имя пользователя</param>
        /// <param name="key">ключ пользователя</param>
        public B23(String username, String key)
        {
            _username = username;
            _apikey = key;
        }

        /// <summary>
        /// Преобразование одного типа данных в другой
        /// </summary>
        /// <param name="sInData">входные данные</param>
        /// <param name="sInType">входной тип</param>
        /// <param name="sOutType">выходной тип</param>
        /// <returns>Данные выходного типа</returns>
        /// <remarks>The fuction has bad code style</remarks>
        public override String ConvertDataTo(string sInData, ItemType sInType, ItemType sOutType)
        {
            if(sInType == ItemType.Clicks) return null;//cant be!
            if(sOutType == ItemType.User) return null;//cant be!
            if (sInType == sOutType) return sInData;

            //
            string url = null;
            if(sInType == ItemType.FullUrl)
            {
                url = String.Format("http://b23.ru/api/shorten/{0}#", sInData);
            }
            if (sOutType == ItemType.FullUrl)//expand
            {
                sInData = sInData.Replace("http://", "").Replace("b23.ru/","");
                url = String.Format("http://b23.ru/api/expand/{0}#", sInData);
            }
            if(sOutType == ItemType.Clicks)
            {
                sInData = sInData.Replace("http://", "").Replace("b23.ru/", "");
                url = String.Format("http://b23.ru/api/info/{0}#", sInData);                
            }

            if (String.IsNullOrEmpty(url)||String.IsNullOrEmpty(_username)||String.IsNullOrEmpty(_apikey))
                return null;//no way to waste time

            try
            {
                NetworkCredential myNetworkCredential = new NetworkCredential(_username, _apikey);
                CredentialCache myCredentialCache = new CredentialCache {{new Uri(url), "Basic", myNetworkCredential}};

                HttpWebRequest request = MakeRequest(url); //prepare web request
                request.PreAuthenticate = true;
                request.Credentials = myCredentialCache;

                HttpWebResponse resp = (HttpWebResponse) request.GetResponse();
                StreamReader responseStream = new StreamReader(resp.GetResponseStream()); //prepare responese holder
                String response = responseStream.ReadToEnd(); //fill up response
                responseStream.Close(); //Close stream
                if (resp.StatusCode == HttpStatusCode.OK)
                {
                    if (sOutType == ItemType.Clicks) //we recieve a big XML with data
                    {
                        Match m = Regex.Match(response, @"<clicks>(\d+)</clicks>",
                                              RegexOptions.Singleline | RegexOptions.IgnoreCase);
                        if (m.Success) return m.Groups[1].Value;
                    }
                    return response;
                }
            }catch(Exception e1)
            {
                Debug.Write(e1);
            }
            return null;
        }
    }
}
